import json
from legocalendar.models.reswell.MySQLwrapper import MySQLwrapper
from legocalendar.models.reswell.WufooWrapper import WufooWrapper

def getWrapper(config, key):
    _type = config['type'].lower()
    if _type == 'mysql': return MySQLwrapper(config,key)
    if _type == 'wufoo': return WufooWrapper(config,key)
    """ add more wrappers here """


class FederatedDatabase:
    """ A singleton class that manages the remote data sources.  """
    
    __CONFIG_PATH__ = "./legocalendar/config/dataSources.conf"
    __config = json.load(open(__CONFIG_PATH__, 'r'))
    __key = __config['key']
    __wrappers = {}


    def __init__(self):
        print("Instantiating Federated Database")
        self.__wrappers = dict(map(lambda conf : (conf['name'], getWrapper(conf, self.__key)) ,
                              self.__config['databases'] ))
        

    def getSchema(self):
        """
        Returns a list of dict objects representing each data source's schema.
        Only returns schemas for wrappers that contain at least one table.
        """
        return filter(lambda d: d['tables'] != [], 
                      [self.__wrappers[name].getSchema() for name in self.__wrappers])

    
    def fullJoin(self, tables):
        """ Takes a list of table dicts and joins them on a common key  """
        final = []
        keys = []

        for data in tables:
            keys += data.keys()

        keys = list(set(keys)) #unique primary keys
        lengths = map(lambda x: len(x.values()[:1]), tables)
        
        for key in keys:
            row = []
            for i in range(len(tables)):
                if key not in tables[i].keys():
                    row += ['']*lengths[i]
                else:
                    row += tables[i][key] #make a row for each primary key
            final.append(row) #append it to final table

        print(final)
        return final
    
    def query(self, databases):
        """ Takes a Dictionary representing the data we want from the wrappers """
        queries = []
        for db in databases['databases']:
            queries.append(self.__wrappers[db['name']].query(db))
        return self.fullJoin(queries)
